<template>
	<div class="calendar">
		<section class="header">
			<el-icon @click="handlePreMonth">
				<ArrowLeftBold />
			</el-icon>
			<div class="title">{{ selectData.year }}年{{ selectData.month }}月</div>
			<el-icon @click="handleNextMonth">
				<ArrowRightBold />
			</el-icon>
		</section>

		<ul class="week-area">
			<li class="week-item" v-for="(item, index) in weekArr" :key="index">
				<span class="week-font calendar-item">{{ item }}</span>
			</li>
		</ul>
		<section ref="calendar" class="data-container" :style="{
			height: isWeekView ? `${itemHeight}px` : `${lineNum * itemHeight}px`,
			transitionDuration: `${needHeightAnimation ? transitionDuration : 0}s`
		}">
			<section class="month-area"
				:style="{ transform: `translateX(${-(translateIndex + 1) * 100}%)`, transitionDuration: `${needAnimation ? transitionDuration : 0}s` }">
				<div class="banner-area"
					:style="{ transitionDuration: `${needHeightAnimation ? transitionDuration : 0}s` }">
					<ul v-for="(monthItem, monthIndex) in allDataArr" :key="monthIndex" class="data-area"
						:style="{ transform: `translateX(${(translateIndex) * 100}%)`, transitionDuration: `${transitionDuration}s` }">
						<li v-for="(item, index) in monthItem" :key="index" :class="[
							'data-item',
							{ 'selected': item.isSelected },
							{ 'other-item': item.type !== 'normal' && !isWeekView },
						]" :style="`height: ${itemHeight}px`" @click="checkoutDate(item)">
							<span class="data-font calendar-item">{{ item.day }}</span>
						</li>
					</ul>
				</div>
			</section>
		</section>
	</div>

	<div class="schedule_box">
		<div class="schedule_title">{{ selectData.weekDay }} {{ selectData.month }}月{{ selectData.day }}日</div>
		<div class="schedule_list" v-if="scheduleData.length !=0">
			<div v-for="(item, index) in scheduleData" :key="index" class="schedule_item">
				<div class="schedule_time">{{ item.time }}</div>
				<div class="schedule_description">{{ item.description }}</div>
			</div>
		</div>
	</div>
</template>

<script setup name="calender">
import xxx from "./xxx.json"
const scheduleData = ref([])
const weekArr = ref(['周日', '周一', '周二', '周三', '周四', '周五', '周六']) // 星期数组  
const dataArr = ref([]) // 当前可视区域数据  
const allDataArr = ref([]) // 轮播数组  
let selectData = reactive({
	year: new Date().getFullYear(),
	month: new Date().getMonth() + 1,
	day: new Date().getDate(),
	weekDay: new Date().getDay()
}); // 选中日期信息  
const isSelectedCurrentDate = ref(false) // 是否点选当前月份信息  
const translateIndex = ref(0) // 轮播所在位置  
const transitionDuration = ref(0.3) // 动画持续时间  
const needAnimation = ref(true) // 左右滑动是否需要动画    

const isWeekView = ref(false) // 周视图还是月视图  
const itemHeight = ref(50) // 子元素行高  
const needHeightAnimation = ref(false) // 高度变化是否需要动画  

const lineNum = ref(0) // 当前视图总行数  
const lastWeek = ref([]) // 周视图 前一周数据  
const nextWeek = ref([]) // 周视图 后一周数据  
const isDelay = ref(true) // 是否延迟 (动画结束在处理数据)  

const isClicked = ref(false) // 点选元素

// 生命周期钩子  
onMounted(() => {
	checkoutCurrentDate()
	// 获取当前日期的字符串格式，例如 '2024-10-11'
	const currentDateStr = `${selectData.year}-${selectData.month.toString().padStart(2, '0')}-${selectData.day.toString().padStart(2, '0')}`
	changeList(currentDateStr)
})

// 监听器  
watch(dataArr, (val) => {
	changeAllData(val)
}, { deep: true })

watch(isWeekView, (val) => {
	if (!val) {
		isSelectedCurrentDate.value = false
		changeAllData(dataArr.value)
	}
})
function getWeekDay(year, month, day) {
	const weekDays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
	const date = new Date(year, month - 1, day)
	return weekDays[date.getDay()]
}
// 更新轮播数组
function changeAllData(val) {
	if (isSelectedCurrentDate.value && !isWeekView.value) return

	const preDate = getPreMonth()
	const preDataArr = getMonthData(preDate, true)
	const nextDate = getNextMonth()
	const nextDataArr = getMonthData(nextDate, true)

	if (isWeekView.value) {
		const sliceStart = dealWeekViewSliceStart()
		preDataArr.splice(sliceStart, 7, ...lastWeek.value)
		nextDataArr.splice(sliceStart, 7, ...nextWeek.value)
	}

	const delayHandle = (isDelay) => {
		allDataArr.value = [preDataArr, val, nextDataArr]
		needAnimation.value = false
		translateIndex.value = 0
		if (isDelay && isDelay.value) {
			isDelay.value = false
		}
	}

	if (isDelay.value) {
		delayHandle(isDelay.value)
		return
	}

	setTimeout(() => {
		delayHandle()
	}, isClicked.value && isWeekView.value ? 0 : transitionDuration.value * 1000)
}
// 获取当前日期
function getCurrentDate() {
	selectData.value = {
		year: new Date().getFullYear(),
		month: new Date().getMonth() + 1,
		day: new Date().getDate()
	}
}
// 获取指定月份数据
function getMonthData(date, unSelected = false) {
	const { year, month, day } = date
	let dataArr = []
	let daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

	if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
		daysInMonth[1] = 29
	}

	const monthStartWeekDay = new Date(year, month - 1, 1).getDay()
	const monthEndWeekDay = new Date(year, month, 1).getDay() || 7

	const preInfo = getPreMonth(date)
	const nextInfo = getNextMonth()

	for (let i = 0; i < monthStartWeekDay; i++) {
		let preObj = {
			type: 'pre',
			day: daysInMonth[preInfo.month - 1] - (monthStartWeekDay - i - 1),
			month: preInfo.month,
			year: preInfo.year
		}
		dataArr.push(preObj)
	}

	for (let i = 0; i < daysInMonth[month - 1]; i++) {
		let itemObj = {
			type: 'normal',
			day: i + 1,
			month,
			year,
			isSelected: day === i + 1 && !unSelected
		}
		dataArr.push(itemObj)
	}

	for (let i = 0; i < 7 - monthEndWeekDay; i++) {
		let nextObj = {
			type: 'next',
			day: i + 1,
			month: nextInfo.month,
			year: nextInfo.year
		}
		dataArr.push(nextObj)
	}

	return dataArr
}
// 点选切换日期
function checkoutDate(selectDatax) {
	isSelectedCurrentDate.value = true
	isClicked.value = true

	if (isWeekView.value && selectDatax.type !== 'normal') {
		needAnimation.value = false
		needHeightAnimation.value = false
	}

	if (selectDatax.type === 'next') {
		translateIndex.value += 1
		dealMonthData('NEXT_MONTH', selectDatax.day)
		return
	}

	if (selectDatax.type === 'pre') {
		translateIndex.value -= 1
		dealMonthData('PRE_MONTH', selectDatax.day)
		return
	}

	// 更新选中的日期，不再重置day
	selectData.day = selectDatax.day
	selectData.weekDay = getWeekDay(selectDatax.year, selectDatax.month, selectDatax.day) // 更新星期几

	const oldSelectIndex = dataArr.value.findIndex(item => item.isSelected && item.type === 'normal')
	const newSelectIndex = dataArr.value.findIndex(item => item.day === selectDatax.day && item.type === 'normal')

	if (dataArr.value[oldSelectIndex]) {
		dataArr.value[oldSelectIndex].isSelected = false;
	}
	if (dataArr.value[newSelectIndex]) {
		dataArr.value[newSelectIndex].isSelected = true;
	}
	// 更新日程
	const mydateStr = `${selectDatax.year}-${selectDatax.month.toString().padStart(2, '0')}-${selectDatax.day.toString().padStart(2, '0')}`
	changeList(mydateStr)
}

// 获取前(后)一个月的年月日信息
function getPreMonth(date, appointDay) {
	let { year, month, day } = date || selectData
	if (month === 1) {
		year -= 1
		month = 12
	} else {
		month -= 1
	}
	day = appointDay || selectData.day
	// 确保目标月份有当前选中的日，否则设为该月最后一天
	const daysInMonth = getDaysInMonth(year, month)
	if (day > daysInMonth) {
		day = daysInMonth
	}
	return { year, month, day }
}

function getNextMonth(appointDay) {
	let { year, month, day } = selectData
	if (month === 12) {
		year += 1
		month = 1
	} else {
		month += 1
	}
	day = appointDay || selectData.day
	// 确保目标月份有当前选中的日，否则设为该月最后一天
	const daysInMonth = getDaysInMonth(year, month)
	if (day > daysInMonth) {
		day = daysInMonth
	}
	return { year, month, day }
}

// 切换上(下)一月
function handlePreMonth() {
	dealMonthData('PRE_MONTH')
}
function handleNextMonth() {
	dealMonthData('NEXT_MONTH')
}

// 获取某个月的天数
function getDaysInMonth(year, month) {
	const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
	if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
		daysInMonth[1] = 29 // 闰年
	}
	return daysInMonth[month - 1]
}
// 处理月数据
function dealMonthData(type, appointDay) {
	isSelectedCurrentDate.value = false

	switch (type) {
		case 'PRE_MONTH':
			selectData = getPreMonth('', appointDay)
			break
		case 'NEXT_MONTH':
			selectData = getNextMonth(appointDay)
			break
		default:
			break
	}

	// 重新获取数据，并确保日保持不变
	dataArr.value = getMonthData(selectData)
	lineNum.value = Math.ceil(dataArr.value.length / 7)

	// 获取当前选中的日期字符串，例如 '2024-09-11'
	const currentDateStr = `${selectData.year}-${selectData.month.toString().padStart(2, '0')}-${selectData.day.toString().padStart(2, '0')}`

	// 更新日程
	changeList(currentDateStr)
}

// 今日
function checkoutCurrentDate() {
	isDelay.value = true
	selectData.weekDay = getWeekDay(selectData.year, selectData.month, selectData.day)
	getCurrentDate()
	dealMonthData()
}
// 显示日程
function changeList(date) {
	const matchedItem = xxx.schedule.find(item => item.date === date)
	if (matchedItem) {
		scheduleData.value = matchedItem.tasks // 这里直接获取 tasks 数组
	} else {
		scheduleData.value = [] // 如果没有找到日程，清空任务列表
	}
}
</script>

<style lang="scss" scoped>
.calendar {
	overflow-x: hidden;
}

.header {
	padding: 0 5px;
	font-size: 16px;
	font-weight: 500;
	color: #2b4450;
	line-height: 44px;
	margin: 0 calc((14.285% - 40px) / 2 + 6px);
	display: flex;
	align-items: center;
	padding-top: 12px;
}

.title {
	flex: 1;
	text-align: center;
}

.header .icon {
	width: 20px;
	height: 20px;
}

.header .icon-left {
	margin-right: 10px;
}

.header .icon-right {
	margin-left: 10px;
}

.calendar-content {
	padding: 0 5px;
}

.week-area {
	padding: 0 calc((14.285% - 28px) / 2);
}

.calendar-item {
	display: block;
	width: 40px;
	height: 40px;
	text-align: center;
	line-height: 40px;
}

.calendar-item {
	display: block;
	width: 40px;
	height: 40px;
	text-align: center;
	line-height: 40px;
}

.selected .calendar-item {
	background: #369aff;
	border-radius: 50%;
	color: #fff;
}

ul {
	padding: 0;
	margin: 0;
}

.week-area {
	width: 100%;
	display: flex;

}

.week-item {
	height: 45px;
	flex: 0 0 14.285%;
	display: flex;
	align-items: center;
	justify-content: center;
}

.week-font {
	font-size: 15px;
	color: #2b4450;
	font-weight: 500;
}

.data-container {
	overflow: hidden;
	position: relative;
	padding: 0 calc((14.285% - 28px) / 2);
}

.banner-area {
	width: 300%;
	display: flex;
}

.data-area {
	width: 100%;
	height: 100%;
	display: flex;
	flex-flow: row wrap;
}

.data-item {
	flex: 0 0 14.285%;
	display: flex;
	align-items: center;
	justify-content: center;
}

.data-font {
	color: #2b4450;
	font-size: 15px;
	font-weight: 400;
}

.other-item .data-font {
	color: #ccc;
}

.schedule_box {
	margin: 16px calc((14.285% - 28px) / 2 + 6px);
	padding: 16px;
	background-color: #f9f9f9;
	border-radius: 10px;
}
.schedule_list{
	padding-top: 20px;
}
.schedule_item {
	display: flex;
	line-height: 22px;
    font-size: 14px;

	&:not(:last-child) {
		padding-bottom: 12px;
	}

}

.schedule_time {
	width: 48px;
}

.schedule_title {
	font-size: 16px;
	font-weight: 600;
	color: #2b4450;
}
</style>